package com.yx.controller;

import com.yx.aop.annotation.LogRecord;
import com.yx.aop.enums.SysLogType;
import com.yx.aop.enums.SysLogUnit;
import com.yx.data.Result;
import com.yx.enums.ResultEnum;
import com.yx.enums.ShiroMessageEnum;
import com.yx.util.CaptchaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;

/**
 * @Description: login
 * @Auther: zcz
 * @create 2020/4/16 11:51
 */
@RestController
@Slf4j
public class LoginController {

    public static final String KEY_CAPTCHA = "KEY_CAPTCHA";

    /**
     * 退出
     * @return
     */
    @GetMapping("/logout")
    public Result logout() {
        Subject subject = SecurityUtils.getSubject();
        if (subject != null) {
            subject.getSession().stop();
            subject.logout();
        }
        return new Result(ResultEnum.SUCCESS.getCode(), ShiroMessageEnum.SHIRO_AUTHC_LOGOUT_MESSAGE.getMsg());
    }

    /**
     * 登录
     * @param username
     * @param password
     * @param rememberMe
     * @return
     */
    @PostMapping("/login")
    public Result login(@RequestParam("username") String username,
                              @RequestParam("password") String password,
                              @RequestParam("captcha") String captcha,
                              boolean rememberMe) {
        return executeLogin(username, password, captcha, rememberMe);
    }

    /**
     * 登录方法
     * @return
     */
    public Result executeLogin(String username, String password, String captcha, boolean rememberMe) {
        log.info("登录开始，operNo：" + username + ",rememberMe：" + rememberMe + ",captcha:" + captcha);
        String sessionCaptcha = (String) SecurityUtils.getSubject().getSession().getAttribute(KEY_CAPTCHA);
        if (StringUtils.isBlank(captcha) || !captcha.equalsIgnoreCase(sessionCaptcha)) {
            return Result.fail(ShiroMessageEnum.SHIRO_CAPTCHA_EXCEPTION_MESSAGE.getMsg());
        }
        UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
        Subject subject = SecurityUtils.getSubject();
        log.info("登录结束！");
        return exceptionMessage(subject, token);
    }

    /**
     * 执行登录
     * @param subject
     * @param token
     * @return
     */
    public Result exceptionMessage(Subject subject, UsernamePasswordToken token) {
        try {
            subject.login(token);
            return Result.ok(ResultEnum.SUCCESS.getCode(), ShiroMessageEnum.SHIRO_AUTHC_LOGIN_MESSAGE.getMsg());
        } catch (UnknownAccountException unknownAccountException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_UNKNOWNACCOUNTEXCEPTION_MESSAGE.getMsg());
        } catch (IncorrectCredentialsException incorrectCredentialsException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_INCORRECTCREDENTIALSEXCEPTION_MESSAGE.getMsg());
        } catch (LockedAccountException lockedAccountException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_LOCKEDACCOUNTEXCEPTION_MESSAGE.getMsg());
        } catch (DisabledAccountException disabledAccountException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_DISABLEDACCOUNTEXCEPTION_MESSAGE.getMsg());
        } catch (ExcessiveAttemptsException excessiveAttemptsException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_EXCESSIVEATTEMPTSEXCEPTION_MESSAGE.getMsg());
        } catch (ConcurrentAccessException concurrentAccessException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_CONCURRENTACCESSEXCEPTION_MESSAGE.getMsg());
        } catch (AccountException accountException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_ACCOUNTEXCEPTION_MESSAGE.getMsg());
        } catch (UnsupportedTokenException unsupportedTokenException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_UNSUPPORTEDTOKENEXCEPTION_MESSAGE.getMsg());
        } catch (CredentialsException credentialsException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_CREDENTIALSEXCEPTION_MESSAGE.getMsg());
        } catch (AuthenticationException authenticationException) {
            return Result.fail(ResultEnum.FAIL.getCode(), ShiroMessageEnum.SHIRO_AUTHC_AUTHENTICATIONEXCEPTION_MESSAGE.getMsg());
        }
    }


    /**
     * 获取验证码
     * @param request
     * @param response
     */
    @RequestMapping("/Captcha.jpg")
    public void getCaptcha(HttpServletRequest request, HttpServletResponse response) {
        // 设置相应类型,告诉浏览器输出的内容为图片
        response.setContentType("image/jpeg");
        // 不缓存此内容
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        try {
            HttpSession session = request.getSession();
            CaptchaUtil tool = new CaptchaUtil();
            StringBuffer code = new StringBuffer();
            BufferedImage image = tool.genRandomCodeImage(code);
            session.removeAttribute(KEY_CAPTCHA);
            session.setAttribute(KEY_CAPTCHA, code.toString());
            // 将内存中的图片通过流动形式输出到客户端
            ImageIO.write(image, "JPEG", response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
